package com.csx.micrometer.simple.sentinel.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * @author cuisongxu
 * @date 2023/2/3 13:46
 */

@RestController
public class HelloController {

    static {
//        initFlowRules();
//        initDegradeRules();
    }

    @SentinelResource(value = "/testFlow", blockHandler = "testFlowBlockHandler", fallback = "")
    @GetMapping("/testFlow")
    public String testFlow() {
        System.out.println("test Flow");
        return "test Flow";
    }

    /**
     * 兜底方法的 权限标识符 返回值 要与业务方法保持一致，同时参数上要有 对应的异常
     * @param e
     * @return
     */
    public String testFlowBlockHandler(BlockException e) {
        return "sentinel flow block !";
    }

    public String testExceptionHandler(Exception e) {
        return "test";
    }

    @SentinelResource(value = "/testDegrade", blockHandler = "testDegradeBlockHandler")
    @GetMapping("/testDegrade/{code}")
    public String testDegrade(@PathVariable("code") Integer code) {
        System.out.println("test Degrade");
        if(code.equals(0)) {
            throw new RuntimeException();
        } else {
            return "success";
        }


    }

    @SentinelResource(value = "/testDegrade2", blockHandler = "testDegradeBlockHandler")
    @GetMapping("/testDegrade2/{code}")
    public String testDegrade2(@PathVariable("code") Integer code) {
        System.out.println("test Degrade2");
        if(code.equals(0)) {
            throw new RuntimeException();
        } else {
            return "success";
        }
    }

    public String testDegradeBlockHandler(BlockException e) {
        System.out.println("degrade block");
        return "sentinel degrade block !";
    }

    private static void initFlowRules() {

        List<FlowRule> rules = new ArrayList<>();

        // 限流规则
        FlowRule rule = new FlowRule();
        rule.setResource("/testFlow");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // set limit QPS to 20
        rule.setCount(1);
        rules.add(rule);

        FlowRuleManager.loadRules(rules);
    }
    private static void initDegradeRules() {

        List<DegradeRule> rules = new ArrayList<>();

        // 熔断规则
        DegradeRule rule = new DegradeRule("/testDegrade")
                .setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType())
                .setCount(0.5d) // set ratio thrashold to 50%
                .setStatIntervalMs(20000)
                .setMinRequestAmount(1)
                .setTimeWindow(2);

        // 熔断规则
        DegradeRule rule2 = new DegradeRule("/testDegrade2")
                .setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType())
                .setCount(0.5d) // set ratio thrashold to 50%
                .setStatIntervalMs(20000)
                .setMinRequestAmount(1)
                .setTimeWindow(2);
        rules.add(rule);
        rules.add(rule2);
        DegradeRuleManager.loadRules(rules);
    }

}
